package cn.lwalan.serverUtils.gen;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;

import cn.lwalan.commonUtils.FileUtils;
import cn.lwalan.commonUtils.XmlUtil;
import freemarker.template.Configuration;
import freemarker.template.Template;

public class GenServerUtil {
	
	private static String AUTHOR = "alan";
	private static String VERSION = "1.0.1";
	private static String DESC = "";
	private static Logger logger = LoggerFactory.getLogger(GenServerUtil.class);
	
	@SuppressWarnings("rawtypes")
	private static Server getServerModelold(Class clazz,
			Server model) throws Exception, IllegalAccessException{
		List<Function> functions = new ArrayList<Function>();
		List<String> importClass = new ArrayList<String>();
		Method[] methods = clazz.getMethods();
		//int index=0;
		for (Method method : methods) {
			//index++;
			Function funciotn = new Function();
			String returnTypeName = "";
			Type returnType = method.getGenericReturnType();// 返回类型
			//System.out.println("type = "+returnType);
			if(returnType instanceof ParameterizedType){
				Type[] types = ((ParameterizedType) returnType).getActualTypeArguments();// 泛型类型列表
				if(types.length == 1){
					Type type = types[0];
					//System.out.println("type = "+type);
					String str = type.toString();
					String[] arr = str.split("[ ]");
					String strClass = arr[1];
					if(!importClass.contains(strClass) && !strClass.equals("void")){
						importClass.add(strClass);
					}
					String[] arr2 = strClass.split("[.]");
					String className = arr2[arr2.length-1];
					returnTypeName ="List<"+className+">";
				}else{
					throw new Exception("不支持的类型！");
				}
			}else{
				returnTypeName = method.getReturnType().getSimpleName();
				if(!returnTypeName.equals("int") 
						&& !returnTypeName.equals("Integer")
						&& !returnTypeName.equals("String")
						&& !returnTypeName.equals("void")
						&& !returnTypeName.equals("long")
						&& !returnTypeName.equals("Long")){
					String strClass = method.getReturnType().getName();
					if(!importClass.contains(strClass)){
						importClass.add(strClass);
					}
				}else{
				}
			}
			//System.out.println(index+"=====returnTypeName="+returnTypeName);
			funciotn.setReturnType(returnTypeName);
			String name = method.getName();
			//System.out.println(index+"----name="+name);
			funciotn.setName(name);
			Type[] paramTypeList = method.getGenericParameterTypes();// 方法的参数列表
			List<Parms> parmsList = new ArrayList<>();
			//int paramIndex = 0;
			for (Type paramType : paramTypeList) {
				//System.out.println(index+"---param=" + paramType);// 参数类型
				//paramIndex++;
				Parms parms = new Parms();
				String strt = paramType.toString();
				String[] arrT = strt.split("[ ]");
				String strParamType = arrT.length == 2?arrT[1]:arrT[0];
				//System.out.println(index+"---param=" + strParamType);// 参数类型
				if (paramType instanceof ParameterizedType)/**//* 如果是泛型类型 */{
					throw new Exception("不支持的类型！");
				}else{
					if(!strParamType.equals("int") 
							&& !strParamType.equals("java.lang.Integer")
							&& !strParamType.equals("java.lang.String")
							&& !strParamType.equals("long")
							&& !strParamType.equals("java.lang.Long")){
						//System.out.println("-------------");
						String strClass = strParamType;
						if(!importClass.contains(strClass)){
							importClass.add(strClass);
						}
						String[] temp = strParamType.split("[.]");
						String parmType = temp[temp.length-1];
						String parmName = parmType.substring(0, 1).toLowerCase()+parmType.substring(1);
						parms.setType(parmType);
						parms.setName(parmName);
					}else{
						String[] temp = strParamType.split("[.]");
						String parmType = temp[temp.length-1];
						//String parmName = parmType.substring(0, 1).toLowerCase()+parmType.substring(1);
						String parmName = "key";
						parms.setType(parmType);
						parms.setName(parmName);
					}
				}
				parmsList.add(parms);
			}
			funciotn.setParmsList(parmsList);
			functions.add(funciotn);
		}
		model.setFunctionList(functions);
		model.setImportClass(importClass);
		return model;
	}
	
	@SuppressWarnings("rawtypes")
	private static Server getServerModel(Class clazz,
			Server model) throws Exception, IllegalAccessException{
		List<Function> functions = new ArrayList<Function>();
		List<String> importClass = new ArrayList<String>();
		Method[] methods = clazz.getMethods();
		//int index=0;
		for (Method method : methods) {
			//index++;
			Function funciotn = new Function();
			String returnTypeName = "";
			Type returnType = method.getGenericReturnType();// 返回类型
			//System.out.println("type = "+returnType);
			if(returnType instanceof ParameterizedType){
				Type[] types = ((ParameterizedType) returnType).getActualTypeArguments();// 泛型类型列表
				if(types.length == 1){
					Type type = types[0];
					//System.out.println("type = "+type);
					String str = type.toString();
					String[] arr = str.split("[ ]");
					String strClass = arr[1];
					if(!importClass.contains(strClass) && !strClass.equals("void")){
						importClass.add(strClass);
					}
					String[] arr2 = strClass.split("[.]");
					String className = arr2[arr2.length-1];
					returnTypeName ="List<"+className+">";
				}else{
					throw new Exception("不支持的类型！");
				}
			}else{
				returnTypeName = method.getReturnType().getSimpleName();
				if(!returnTypeName.equals("int") 
						&& !returnTypeName.equals("Integer")
						&& !returnTypeName.equals("String")
						&& !returnTypeName.equals("void")
						&& !returnTypeName.equals("long")
						&& !returnTypeName.equals("Long")){
					String strClass = method.getReturnType().getName();
					if(!importClass.contains(strClass)){
						importClass.add(strClass);
					}
				}else{
				}
			}
			//System.out.println(index+"=====returnTypeName="+returnTypeName);
			funciotn.setReturnType(returnTypeName);
			String name = method.getName();
			//System.out.println(index+"----name="+name);
			funciotn.setName(name);
			List<Parms> parmsList = new ArrayList<>();
			Parameter[] parameters = method.getParameters();
	        for (final Parameter parameter : parameters){
	        	Parms parms = new Parms();
	        	//System.out.println(funciotn.getName());
	        	//System.out.println("***parameterName="+parameter.getName());
	        	//System.out.println("***type1="+parameter.getType().getCanonicalName());
	        	//System.out.println("***type2="+parameter.getType().getName());
	        	//System.out.println("***type3="+parameter.getType().getSimpleName());
	        	//System.out.println("***parameter.getParameterizedType()="+parameter.getParameterizedType());
	        	String type = parameter.getType().getSimpleName();
	        	parms.setName(parameter.getName());
	        	parms.setType(type);
	        	//如果是泛型类型 
	        	if (parameter.getParameterizedType() instanceof ParameterizedType){
	        		//System.out.println("parameter.isVarArgs()="+parameter.isVarArgs());
	        		throw new Exception("不支持的类型！");
	        	}
	        	if(!type.equals("int") 
						&& !type.equals("Integer")
						&& !type.equals("String")
						&& !type.equals("double")
						&& !type.equals("Double")
						&& !type.equals("float")
						&& !type.equals("Float")
						&& !type.equals("long")
						&& !type.equals("Long")){
					String strClass = parameter.getType().getName();
					if(!importClass.contains(strClass)){
						importClass.add(strClass);
					}
				}else{
				}
	        	parmsList.add(parms);
	        }
			funciotn.setParmsList(parmsList);
			functions.add(funciotn);
		}
		model.setFunctionList(functions);
		model.setImportClass(importClass);
		return model;
	}
	
	@SuppressWarnings({ "unchecked", "deprecation", "rawtypes" })
	private static boolean GenServerCodeToFile(String templatesFilePath,Class mapperClass,
			String serverName,String packageName,
			String author,String version,String desc) throws Exception{
		Server model = new Server();
		model.setPackageName(packageName);
		model.setClassAuthor(author);
		model.setClassName(serverName);
		model.setClassVersion(version);
		model.setDesc(desc);
		model = getServerModel(mapperClass,model); 
		Resource resource = new ClassPathResource(templatesFilePath); 
		InputStream is = resource.getInputStream();
		BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
		StringBuilder sb = new StringBuilder();
		while (true) {
			String line = br.readLine();
			if (line == null){
				break;
			}
			sb.append(line).append("\r\n");
		}
		if (is != null) {
			is.close();
		}
		if (br != null) {
			br.close();
		}
		StringWriter result = new StringWriter();
		Template t = new Template("name", new StringReader(sb.toString()), new Configuration());
		t.process(model, result);
		Map<String,String> map = XmlUtil.xmlToMap(result.toString());
		String projectPath =""; 
		File file = new DefaultResourceLoader().getResource("").getFile();
		if (file != null){
			while(true){
				File f = new File(file.getPath() + File.separator + "src" + File.separator + "main");
				if (f == null || f.exists()){
					break;
				}
				if (file.getParentFile() != null){
					file = file.getParentFile();
				}else{
					break;
				}
			}
			projectPath = file.toString();
		}
		String fileName = projectPath + File.separator 
				+ StringUtils.replaceEach(map.get("filePath")+ "/", 
						new String[]{"//", "/", "."}, new String[]{File.separator, File.separator, File.separator})
				+map.get("fileName");
		logger.debug(" fileName === " + fileName);
		// 创建并写入文件
		String content = map.get("content");
		//logger.debug("comtent = "+content);
		if (FileUtils.createFile(fileName)){
			FileUtils.writeToFile(fileName, content, true);
			logger.debug(" file create === " + fileName);
			//System.out.println(" file create === " + fileName);
			logger.info("生成成功");
			return true;
		}else{
			logger.debug(" file extents === " + fileName);
			logger.info("文件已存在");
			return false;
		}
	}
	
	@SuppressWarnings("rawtypes")
	private static Server getServerImplModelold(Class clazz,
			Server model,
			String serverClassName) throws Exception, IllegalAccessException{
		List<Function> functions = new ArrayList<Function>();
		List<String> importClass = new ArrayList<String>();
		String strNt = clazz.getName();
		importClass.add(strNt);
		importClass.add(serverClassName);
		String[] arrNt = strNt.split("[.]");
		strNt = arrNt[arrNt.length-1];
		model.setMapperType(strNt);
		Method[] methods = clazz.getMethods();
		//int index=0;
		for (Method method : methods) {
			//index++;
			Function funciotn = new Function();
			String returnTypeName = "";
			Type returnType = method.getGenericReturnType();// 返回类型
			//System.out.println("type = "+returnType);
			if(returnType instanceof ParameterizedType){
				Type[] types = ((ParameterizedType) returnType).getActualTypeArguments();// 泛型类型列表
				if(types.length == 1){
					Type type = types[0];
					//System.out.println("type = "+type);
					String str = type.toString();
					String[] arr = str.split("[ ]");
					String strClass = arr[1];
					if(!importClass.contains(strClass) && !strClass.equals("void")){
						importClass.add(strClass);
					}
					String[] arr2 = strClass.split("[.]");
					String className = arr2[arr2.length-1];
					returnTypeName ="List<"+className+">";
				}else{
					throw new Exception("不支持的类型！");
				}
			}else{
				returnTypeName = method.getReturnType().getSimpleName();
				if(!returnTypeName.equals("int") 
						&& !returnTypeName.equals("Integer")
						&& !returnTypeName.equals("String")
						&& !returnTypeName.equals("void")
						&& !returnTypeName.equals("long")
						&& !returnTypeName.equals("Long")){
					String strClass = method.getReturnType().getName();
					if(!importClass.contains(strClass)){
						importClass.add(strClass);
					}
				}else{
				}
			}
			//System.out.println(index+"=====returnTypeName="+returnTypeName);
			funciotn.setReturnType(returnTypeName);
			String name = method.getName();
			//System.out.println(index+"----name="+name);
			funciotn.setName(name);
			Type[] paramTypeList = method.getGenericParameterTypes();// 方法的参数列表
			List<Parms> parmsList = new ArrayList<>();
			//int paramIndex = 0;
			for (Type paramType : paramTypeList) {
				//System.out.println(index+"---param=" + paramType);// 参数类型
				//paramIndex++;
				Parms parms = new Parms();
				String strt = paramType.toString();
				String[] arrT = strt.split("[ ]");
				String strParamType = arrT.length == 2?arrT[1]:arrT[0];
				//System.out.println(index+"---param=" + strParamType);// 参数类型
				if (paramType instanceof ParameterizedType)/**//* 如果是泛型类型 */{
					throw new Exception("不支持的类型！");
				}else{
					if(!strParamType.equals("int") 
							&& !strParamType.equals("java.lang.Integer")
							&& !strParamType.equals("java.lang.String")
							&& !strParamType.equals("long")
							&& !strParamType.equals("java.lang.Long")){
						//System.out.println("-------------");
						String strClass = strParamType;
						if(!importClass.contains(strClass)){
							importClass.add(strClass);
						}
						String[] temp = strParamType.split("[.]");
						String parmType = temp[temp.length-1];
						String parmName = parmType.substring(0, 1).toLowerCase()+parmType.substring(1);
						parms.setType(parmType);
						parms.setName(parmName);
					}else{
						String[] temp = strParamType.split("[.]");
						String parmType = temp[temp.length-1];
						//String parmName = parmType.substring(0, 1).toLowerCase()+parmType.substring(1);
						String parmName = "key";
						parms.setType(parmType);
						parms.setName(parmName);
					}
				}
				parmsList.add(parms);
			}
			funciotn.setParmsList(parmsList);
			functions.add(funciotn);
		}
		model.setFunctionList(functions);
		model.setImportClass(importClass);
		return model;
	}
	
	@SuppressWarnings("rawtypes")
	private static Server getServerImplModel(Class clazz,
			Server model,
			String serverClassName) throws Exception, IllegalAccessException{
		List<Function> functions = new ArrayList<Function>();
		List<String> importClass = new ArrayList<String>();
		String strNt = clazz.getName();
		importClass.add(strNt);
		importClass.add(serverClassName);
		String[] arrNt = strNt.split("[.]");
		strNt = arrNt[arrNt.length-1];
		model.setMapperType(strNt);
		Method[] methods = clazz.getMethods();
		//int index=0;
		for (Method method : methods) {
			//index++;
			Function funciotn = new Function();
			String returnTypeName = "";
			Type returnType = method.getGenericReturnType();// 返回类型
			//System.out.println("type = "+returnType);
			if(returnType instanceof ParameterizedType){
				Type[] types = ((ParameterizedType) returnType).getActualTypeArguments();// 泛型类型列表
				if(types.length == 1){
					Type type = types[0];
					//System.out.println("type = "+type);
					String str = type.toString();
					String[] arr = str.split("[ ]");
					String strClass = arr[1];
					if(!importClass.contains(strClass) && !strClass.equals("void")){
						importClass.add(strClass);
					}
					String[] arr2 = strClass.split("[.]");
					String className = arr2[arr2.length-1];
					returnTypeName ="List<"+className+">";
				}else{
					throw new Exception("不支持的类型！");
				}
			}else{
				returnTypeName = method.getReturnType().getSimpleName();
				if(!returnTypeName.equals("int") 
						&& !returnTypeName.equals("Integer")
						&& !returnTypeName.equals("String")
						&& !returnTypeName.equals("void")
						&& !returnTypeName.equals("long")
						&& !returnTypeName.equals("Long")){
					String strClass = method.getReturnType().getName();
					if(!importClass.contains(strClass)){
						importClass.add(strClass);
					}
				}else{
				}
			}
			//System.out.println(index+"=====returnTypeName="+returnTypeName);
			funciotn.setReturnType(returnTypeName);
			String name = method.getName();
			//System.out.println(index+"----name="+name);
			funciotn.setName(name);
			List<Parms> parmsList = new ArrayList<>();
			Parameter[] parameters = method.getParameters();
	        for (final Parameter parameter : parameters){
	        	Parms parms = new Parms();
	        	String type = parameter.getType().getSimpleName();
	        	parms.setName(parameter.getName());
	        	parms.setType(type);
	        	//如果是泛型类型 
	        	if (parameter.getParameterizedType() instanceof ParameterizedType){
	        		//System.out.println("parameter.isVarArgs()="+parameter.isVarArgs());
	        		throw new Exception("不支持的类型！");
	        	}
	        	if(!type.equals("int") 
						&& !type.equals("Integer")
						&& !type.equals("String")
						&& !type.equals("double")
						&& !type.equals("Double")
						&& !type.equals("float")
						&& !type.equals("Float")
						&& !type.equals("long")
						&& !type.equals("Long")){
					String strClass = parameter.getType().getName();
					if(!importClass.contains(strClass)){
						importClass.add(strClass);
					}
				}else{
				}
	        	parmsList.add(parms);
	        }
			funciotn.setParmsList(parmsList);
			functions.add(funciotn);
		}
		model.setFunctionList(functions);
		model.setImportClass(importClass);
		return model;
	}
	
	@SuppressWarnings({ "deprecation", "unchecked", "rawtypes" })
	private static boolean GenServerImplCodeToFile(String templatesFilePath, Class mapperClass,
			String serverName,String serverClassName,String packageName,
			String author,String version,String desc) throws Exception{
		Server model = new Server();
		model.setPackageName(packageName);
		model.setClassAuthor(author);
		model.setClassName(serverName);
		model.setClassVersion(version);
		model.setDesc(desc);
		model = getServerImplModel(mapperClass,model,serverClassName); 
		Resource resource = new ClassPathResource(templatesFilePath); 
		InputStream is = resource.getInputStream();
		BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
		StringBuilder sb = new StringBuilder();
		while (true) {
			String line = br.readLine();
			if (line == null){
				break;
			}
			sb.append(line).append("\r\n");
		}
		if (is != null) {
			is.close();
		}
		if (br != null) {
			br.close();
		}
		StringWriter result = new StringWriter();
		Template t = new Template("name", new StringReader(sb.toString()), new Configuration());
		t.process(model, result);
		//System.out.println(result.toString());
		Map<String,String> map = XmlUtil.xmlToMap(result.toString());
		String projectPath =""; 
		File file = new DefaultResourceLoader().getResource("").getFile();
		if (file != null){
			while(true){
				File f = new File(file.getPath() + File.separator + "src" + File.separator + "main");
				if (f == null || f.exists()){
					break;
				}
				if (file.getParentFile() != null){
					file = file.getParentFile();
				}else{
					break;
				}
			}
			projectPath = file.toString();
		}
		String fileName = projectPath + File.separator 
				+ StringUtils.replaceEach(map.get("filePath")+ "/", 
						new String[]{"//", "/", "."}, new String[]{File.separator, File.separator, File.separator})
				+map.get("fileName");
		logger.debug(" fileName === " + fileName);
		// 创建并写入文件
		String content = map.get("content");
		//logger.debug("comtent = "+content);
		if (FileUtils.createFile(fileName)){
			FileUtils.writeToFile(fileName, content, true);
			logger.debug(" file create === " + fileName);
			//System.out.println(" file create === " + fileName);
			logger.info("生成成功");
			return true;
		}else{
			logger.debug(" file extents === " + fileName);
			logger.info("文件已存在");
			return false;
		}
	}
	
	/**
	 * 
	 * @param templatesFilePath	Server.xml文件路径
	 * @param mapperClass	mapper类
	 * @param className		server名字
	 * @param packageName	包名
	 * @param author	作者
	 * @param version	版本
	 * @param desc		描述
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("rawtypes")
	public static boolean GenServerCode(String templatesFilePath,Class mapperClass,
			String className,String packageName,
			String author,String version,String desc) throws Exception{
		if(StringUtils.isEmpty(author)){
			author = AUTHOR;
		}
		if(StringUtils.isEmpty(version)){
			version = VERSION;
		}
		if(StringUtils.isEmpty(desc)){
			desc = DESC;
		}
		return GenServerCodeToFile(templatesFilePath, mapperClass, className, packageName, author, version, desc);
	}
	
	/**
	 * 
	 * @param templatesFilePath ServerImpl文件路径
	 * @param mapperClass	mapper类
	 * @param serverName	server名字
	 * @param serverClassName	server接口类名
	 * @param packageName	包名
	 * @param author	作者
	 * @param version	版本
	 * @param desc		描述
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("rawtypes")
	public static boolean GenServerImplCode(String templatesFilePath,Class mapperClass,
			String serverName,String serverClassName, String packageName,String author,String version,String desc) throws Exception{
		if(StringUtils.isEmpty(author)){
			author = AUTHOR;
		}
		if(StringUtils.isEmpty(version)){
			version = VERSION;
		}
		if(StringUtils.isEmpty(desc)){
			desc = DESC;
		}
		return GenServerImplCodeToFile(templatesFilePath, mapperClass, serverName,serverClassName, packageName, author, version, desc);
	}
	
	/**
	 * 生成Server与ServerImpl类
	 * @param templatesPath 要带上"/" Service.xml与ServiceImpl.xml的目录
	 * @param mapperClass 	mapper类
	 * @param serverName 	Service名字,会自动加上Service or ServiceImpl
	 * @param packageName	包名
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("rawtypes")
	public static boolean getServerAndServerImplCode(String templatesPath,
			Class mapperClass,String serverName,String packageName,
			String author,String version,String desc) throws Exception{
		if(StringUtils.isEmpty(author)){
			author = AUTHOR;
		}
		if(StringUtils.isEmpty(version)){
			version = VERSION;
		}
		if(StringUtils.isEmpty(desc)){
			desc = DESC;
		}
		return getServerAndServerImplCode( templatesPath+"Service.xml",
				templatesPath+"ServiceImpl.xml",
				 mapperClass, serverName, packageName,
				 author,version,desc);
	}
	
	/**
	 * 生成Server与ServerImpl类
	 * @param templatesServerFilePath Service文件路径
	 * @param templatesServerImpFilelPath ServiceImpl文件路径
	 * @param mapperClass mapper类
	 * @param serverName Service名字,会自动加上Service or ServiceImpl
	 * @param packageName 包名
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("rawtypes")
	public static boolean getServerAndServerImplCode(String templatesServerFilePath,
			String templatesServerImpFilelPath,
			Class mapperClass,String serverName,String packageName,
			String author,String version,String desc) throws Exception{
		if(StringUtils.isEmpty(author)){
			author = AUTHOR;
		}
		if(StringUtils.isEmpty(version)){
			version = VERSION;
		}
		if(StringUtils.isEmpty(desc)){
			desc = DESC;
		}
		boolean isSuccess = GenServerCode(templatesServerFilePath, mapperClass, serverName, packageName,author,version,desc);
		if(!isSuccess){
			return isSuccess;
		}
		isSuccess = GenServerImplCode(templatesServerImpFilelPath, mapperClass, serverName, 
				packageName+"."+serverName+"ServiceImpl",packageName,author,version,desc);
		return isSuccess;
	}
	
}
